package com.erp.mclass;

import android.annotation.TargetApi;
import android.content.Context;
import android.net.Uri;
import android.net.http.SslError;
import android.util.Log;
import android.webkit.SslErrorHandler;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.erp.contacts.Contacts;
import com.erp.util.Httputil;
import com.erp.util.Sputil;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.CertPathValidatorException;
import java.util.Map;
import java.util.UUID;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;

/**
 * Created by Administrator on 2017/1/7/007.
 * 作者：刘洋
 */
public class SslPinningWebViewClient extends WebViewClient {

    private LoadedListener listener;
    private SSLContext sslContext;
    private Context mcontext;
    private WebView webView;
    public SslPinningWebViewClient(Context context, LoadedListener listener,WebView webView)throws IOException  {
        this.listener = listener;
        this.mcontext=context;
        this.webView=webView;
        this.sslContext= Httputil.getSSLContext(context);
    }

    @Override
    public WebResourceResponse shouldInterceptRequest (final WebView view, String url) {
        if(url.contains("mobile=1")){
            return processRequest(Uri.parse(url));
        }
        return super.shouldInterceptRequest(view, url);
    }
    private boolean is=false;
    @Override
    @TargetApi(21)
    public WebResourceResponse shouldInterceptRequest (final WebView view, WebResourceRequest interceptedRequest) {
        Log.d("shouldInterceptRequest",interceptedRequest.getUrl()+"");
        if(interceptedRequest.getUrl().toString().contains("mobile=1") || interceptedRequest.getUrl().toString().contains("https://erp.knoya.com/oss/files")){
            return processRequest(interceptedRequest.getUrl());
        }
        return super.shouldInterceptRequest(view, interceptedRequest);
    }
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        return true;//ture为在webview中打开
    }
    private WebResourceResponse processRequest(final Uri uri) {
        try {
            URL url = new URL(uri.toString());
            HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
            urlConnection.setRequestProperty("COOKIE", Sputil.sp("erp").getString("cookie", ""));
            urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
            InputStream is = urlConnection.getInputStream();
            String contentType = urlConnection.getContentType();
            String encoding = urlConnection.getContentEncoding();
            if(contentType != null) {

                String mimeType = contentType;
                if (contentType.contains(";")) {
                    mimeType = contentType.split(";")[0].trim();
                }
                listener.Loaded(uri.toString());
                return new WebResourceResponse(mimeType, encoding, is);
            }

        } catch (SSLHandshakeException e) {
            if(isCause(CertPathValidatorException.class, e)) {
                listener.PinningPreventedLoading(uri.getHost());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        handler.proceed();
//        super.onReceivedSslError(view, handler, error);
    }

    public static boolean isCause(
            Class<? extends Throwable> expected,
            Throwable exc
    ) {
        return expected.isInstance(exc) || (
                exc != null && isCause(expected, exc.getCause())
        );
    }

    private void addImageClickListner() {

        webView.loadUrl("javascript:(function(){"
                + "var objs = document.getElementsByTagName('img'); "
                + "for(var i=0;i<objs.length;i++)  "
                + "{"
                + "var img = objs[i];   "
                + "    img.style.maxWidth = '100%'; img.style.height = 'auto';  "
                + "}"
                + "})()");
        String jsCode="javascript:(function(){" +
                "var imgs=document.getElementsByTagName(\"img\");" +
                "for(var i=0;i<imgs.length;i++){" +
                "imgs[i].onclick=function(){" +
                "window.jsCallJavaObj.showBigImg(this.src);" +
                "}}})()";
        webView.loadUrl(jsCode);
    }
    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        if(!view.getSettings().getLoadsImagesAutomatically()) {
            view.getSettings().setLoadsImagesAutomatically(true);
        }
        addImageClickListner();
    }
    private static final int TIME_OUT = 8 * 1000;                          //超时时间
    private static final String CHARSET = "utf-8";                         //编码格式
    private static final String PREFIX = "--";                            //前缀
    private static final String BOUNDARY = UUID.randomUUID().toString();  //边界标识 随机生成
    private static final String CONTENT_TYPE = "multipart/form-data";     //内容类型
    private static final String LINE_END = "\r\n";                        //换行
    public static void postRequest(final Map<String, String> strParams, final Map<String, File> fileParams) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection conn = null;
                try {
                    URL url = new URL(Contacts.UPDATA_ERROR+"1");
                    conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("POST");
                    conn.setReadTimeout(TIME_OUT);
                    conn.setConnectTimeout(TIME_OUT);
                    conn.setDoOutput(true);
                    conn.setDoInput(true);
                    conn.setUseCaches(false);//Post 请求不能使用缓存
                    //设置请求头参数
                    conn.setRequestProperty("Connection", "Keep-Alive");
                    conn.setRequestProperty("Charset", "UTF-8");
                    conn.setRequestProperty("Content-Type", CONTENT_TYPE+";boundary=" + BOUNDARY);
                    /**
                     * 请求体
                     */
                    //上传参数
                    DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
                    //getStrParams()为一个
                    dos.writeBytes( getStrParams(strParams).toString() );
                    dos.flush();

                    //文件上传
                    StringBuilder fileSb = new StringBuilder();
                    for (Map.Entry<String, File> fileEntry: fileParams.entrySet()){
                        fileSb.append(PREFIX)
                                .append(BOUNDARY)
                                .append(LINE_END)
                                /**
                                 * 这里重点注意： name里面的值为服务端需要的key 只有这个key 才可以得到对应的文件
                                 * filename是文件的名字，包含后缀名的 比如:abc.png
                                 */
                                .append("Content-Disposition: form-data; name=\"file\"; filename=\""
                                        + fileEntry.getKey() + "\"" + LINE_END)
                                .append("Content-Type: image/jpg" + LINE_END) //此处的ContentType不同于 请求头 中Content-Type
                                .append("Content-Transfer-Encoding: 8bit" + LINE_END)
                                .append(LINE_END);// 参数头设置完以后需要两个换行，然后才是参数内容
                        dos.writeBytes(fileSb.toString());
                        dos.flush();
                        InputStream is = new FileInputStream(fileEntry.getValue());
                        byte[] buffer = new byte[1024];
                        int len = 0;
                        while ((len = is.read(buffer)) != -1){
                            dos.write(buffer,0,len);
                        }
                        is.close();
                        dos.writeBytes(LINE_END);
                    }
                    //请求结束标志
                    dos.writeBytes(PREFIX + BOUNDARY + PREFIX + LINE_END);
                    dos.flush();
                    dos.close();
                    //读取服务器返回信息
                    if (conn.getResponseCode() == 200) {
                        InputStream in = conn.getInputStream();
                        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                        String line = null;
                        StringBuilder response = new StringBuilder();
                        while ((line = reader.readLine()) != null) {
                            response.append(line);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    if (conn!=null){
                        conn.disconnect();
                    }
                }
            }
        }).start();
    }
    /**
     * 对post参数进行编码处理
     * */
    private static StringBuilder getStrParams(Map<String,String> strParams){
        StringBuilder strSb = new StringBuilder();
        for (Map.Entry<String, String> entry : strParams.entrySet() ){
            strSb.append(PREFIX)
                    .append(BOUNDARY)
                    .append(LINE_END)
                    .append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINE_END)
                    .append("Content-Type: text/plain; charset=" + CHARSET + LINE_END)
                    .append("Content-Transfer-Encoding: 8bit" + LINE_END)
                    .append(LINE_END)// 参数头设置完以后需要两个换行，然后才是参数内容
                    .append(entry.getValue())
                    .append(LINE_END);
        }
        return strSb;
    }
}